package com.lsp.lib_uikit.commonrecycler.adapter;

import android.content.Context;
import android.os.Handler;
import android.support.annotation.IntDef;
import android.support.annotation.IntRange;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.lsp.lib_uikit.commonrecycler.rvitem.ListItem;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by palm on 17/7/25.
 * In bxs_android -> com.winbaoxian.view.commonrecycler.adapter
 */

public class HeaderRvAdapter<D> extends BasicRvAdapter<D> {
  private static final int HEADER_VIEW = -1;
  private static final int LIST_ITEM = 0;
  private static final int FOOTER_VIEW = 1;

  @IntDef({ HEADER_VIEW, LIST_ITEM, FOOTER_VIEW })
  private @interface ViewType {
  }

  private static final int ERROR_LAYOUT_ID = Integer.MAX_VALUE;
  @LayoutRes private int layoutId;//itemId
  private Handler handler;
  private final List<View> headerViewList = new ArrayList<>();
  private final List<View> footerViewList = new ArrayList<>();

  public HeaderRvAdapter(Context mContext, @LayoutRes int layoutId) {
    this(mContext, layoutId, null);
  }

  public HeaderRvAdapter(Context mContext, @LayoutRes @IntRange(from = 1) int layoutId,
      Handler handler) {
    super(mContext);
    this.layoutId = layoutId;
    this.handler = handler;
  }

  public HeaderRvAdapter(Context mContext, @LayoutRes @IntRange(from = 1) int layoutId,
      Handler handler, List<D> list) {
    super(mContext, list);
    this.layoutId = layoutId;
    this.handler = handler;
  }

  public void addHeaderView(View headView) {
    headerViewList.add(headView);
    notifyDataSetChanged();
  }

  public void addFooterView(View footView) {
    footerViewList.add(footView);
    notifyDataSetChanged();
  }

  @Override public int getItemCount() {
    return super.getItemCount() + headerViewList.size() + footerViewList.size();
  }

  @Override public int getDefItemViewType(int position) {
    D data = getItem(position);
    if (data == null) {
      // avoid conflict with positive layoutId
      // layoutId should not be zero
      return 0 - position;
    } else {
      int realLayoutId = getRealItemLayoutId(position, data);
      if (realLayoutId <= 0) {
        return ERROR_LAYOUT_ID;
      } else {
        return realLayoutId;
      }
    }
  }

  @LayoutRes protected int getRealItemLayoutId(int position, D data) {
    return layoutId;
  }

  @Override public RecyclerView.ViewHolder onCreateDefViewHolder(ViewGroup parent, int viewType) {
    if (viewType <= 0) {
      viewType = -viewType;
      if (viewType < headerViewList.size()) {
        return new RecyclerView.ViewHolder(headerViewList.get(viewType)) {
        };
      } else {
        viewType -= headerViewList.size() + super.getItemCount();
        return new RecyclerView.ViewHolder(footerViewList.get(viewType)) {
        };
      }
    } else {
      return new RecyclerView.ViewHolder(mLayoutInflater.inflate(viewType, parent, false)) {
      };
    }
  }

  public D getItem(int position) {
    if (getViewType(position) != LIST_ITEM) {
      return null;
    } else {
      position -= headerViewList.size();
      return getAllList().get(position);
    }
  }

  public int getHeaderCount() {
    return headerViewList != null ? headerViewList.size() : 0;
  }

  private @HeaderRvAdapter.ViewType int getViewType(int position) {
    if (position < headerViewList.size()) {
      return HEADER_VIEW;
    } else if (position >= headerViewList.size() + super.getItemCount()) {
      return FOOTER_VIEW;
    } else {
      return LIST_ITEM;
    }
  }

  @Override protected void onDefBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder == null) {
      return;
    }
    D data = getItem(position);
    if (data == null) {
      return;
    }
    final ListItem<D> view = (ListItem<D>) holder.itemView;
    view.setFirst(position == 0);
    view.setPosition(position);
    view.setLast(position == getItemCount() - 1);
    if (handler != null) {
      view.setHandler(handler);
    }
    bindDataToView(view, data);
  }

  protected void bindDataToView(ListItem<D> view, D data) {
    view.attachData(data);
  }
}
